/*
 * Copyright 1999-2101 Alibaba Group.
 *  
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *  
 *      http://www.apache.org/licenses/LICENSE-2.0
 *  
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.alibaba.dubbo.governance.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.springframework.beans.factory.annotation.Autowired;

import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.utils.StringUtils;
import com.alibaba.dubbo.governance.service.CacheService;
import com.alibaba.dubbo.governance.service.ProviderService;
import com.alibaba.dubbo.governance.sync.util.SyncUtils;
import com.alibaba.dubbo.registry.common.domain.Cache;
import com.alibaba.dubbo.registry.common.domain.Provider;

/**
 * IbatisCacheDAO.java
 * @author shihui
 */
public class CacheServiceImpl extends AbstractService implements CacheService{
	@Autowired
	private ProviderService providerService;

	/**
     * 获取符合条件的cache url
     * 
     * @param service 按服务名称搜索
     * @param address 按机器IP搜索
     * @param application 按应用名称搜索
     * */
    private Map<Long, URL> findCacheUrl(String service, String address, String application) {
        Map<String, String> filter = new HashMap<String, String>();
        filter.put(Constants.CATEGORY_KEY, Constants.CONFIGURATORS_CATEGORY);  //获取的数据类型设置为“配置“
        if (service != null && service.length() > 0) {  //根据传入的参数设置过滤参数
        	filter.put(SyncUtils.SERVICE_FILTER_KEY, service);
        }
        if (address != null && address.length() > 0) {
        	filter.put(SyncUtils.ADDRESS_FILTER_KEY, address);
        }
        if (application != null && application.length() > 0) {
        	filter.put(Constants.APPLICATION_KEY, application);
        }
        Map<Long, URL> overridesMap = SyncUtils.filterFromCategory(getRegistryCache(), filter);
        //过滤含有cache参数的url
        Map<Long, URL> cachesMap = new HashMap<Long, URL>();
        Pattern pat = Pattern.compile("^.*&?[a-zA-Z_]{1}[a-zA-Z0-9_]*\\.cache=.*$", Pattern.CASE_INSENSITIVE);  
        Set<Long> keySet = overridesMap.keySet();
        for (Long key : keySet) {
        	URL url = overridesMap.get(key);
        	Matcher mat = pat.matcher(url.toParameterString()); 
    		if(mat.matches()) {
    			cachesMap.put(key, url);
    		}
		}
        return cachesMap;
    }

	/**
	 * 获取有cache配置的所有的服务名
	 * */
	public List<String> findCacheServices() {
		Map<Long, URL> cs = findCacheUrl(null, null, null);
		List<String> serviceList = new ArrayList<String>();
		for(Map.Entry<Long, URL> entry : cs.entrySet()) {
            URL url = entry.getValue();
            String service = url.getServiceKey();
            if(!serviceList.contains(service)) {
            	serviceList.add(service);
            }
        }
		return serviceList;
	}
	
	/**
	 * 将没有缓存的方法填补上去
	 * */
	List<Cache> fillEmptyMethods(Map<String, Cache> cachesMap, List<Provider> providers) {
		List<Cache> list = new ArrayList<Cache>();
		if(providers == null) return list;
		if(cachesMap.isEmpty()) {
			for (Provider provider : providers) {
				for (String method : provider.getMethods()) {
					Cache cache = new Cache();
		        	cache.setMethod(method);  //方法名
		        	cache.setService(provider.getService());
		        	list.add(cache);
				}
	        }
		} else {
			for (Provider provider : providers) {
				for (String method : provider.getMethods()) {
					if(!cachesMap.containsKey(provider.getService() + Constants.HIDE_KEY_PREFIX + method)) {
						Cache cache = new Cache();
			        	cache.setMethod(method);  //方法名
			        	cache.setService(provider.getService());  //服务名
			        	list.add(cache);
					} else {
						list.add(cachesMap.get(provider.getService() + Constants.HIDE_KEY_PREFIX + method));
					}
				}
	        }
		}
		return list;
	}

	/**
	 * 根据不同参数进行查询
	 * 
	 * @param service 服务名
	 * @param address ip地址
	 * @param application 应用名
	 * @param providers 提供者列表
	 * */
	public List<Cache> findByParams(String service, String address, String application) {
		List<Provider> providers = providerService.findByParams(service, address, application);
		if(providers.isEmpty()) new ArrayList<Cache>();
		if (StringUtils.isNotEmpty(service)) {
			return fillEmptyMethods(SyncUtils.url2CacheList(findCacheUrl(service, null, null), providers), providers);  //按服务名搜索
		} else if(StringUtils.isNotEmpty(application)){
			return fillEmptyMethods(SyncUtils.url2CacheList(findCacheUrl(null, null, application), providers), providers);  //按应用名搜索
		}else if(StringUtils.isNotEmpty(address)){
			return fillEmptyMethods(SyncUtils.url2CacheList(findCacheUrl(null, address, null), providers), providers);   //按IP地址搜索
		}
		return new ArrayList<Cache>();
	}
	
	public List<Cache> getCachesByService(String serviceName) {
		List<Cache> caches = new ArrayList<Cache>();
		List<Provider> providers = providerService.findByParams(serviceName, null, null);
		if(providers.isEmpty()) return caches;
		caches.addAll(SyncUtils.url2CacheList(findCacheUrl(serviceName, null, null), providers).values());
		return caches;
	}
}
